#pragma once

#include <stdlib.h>
#include <stdio.h>
// for int conversion
#include <sstream>
#include <string.h>
#include <vector>
#include <iostream>

#include <unistd.h>

#ifdef __WIN32__

	// Networking
	#include <winsock2.h>

	// pdcurses calls it KEY_BACKSPACE
	#define KEY_DELETE 8

#else
	#define KEY_DELETE 127

	// Networking
	#include <sys/socket.h>
	#include <sys/types.h>

	#include <arpa/inet.h>
	#include <netdb.h>
	#include <netinet/in.h>

#endif


#include <signal.h>
#include <curses.h>
#include <errno.h>
#include <math.h>

#include "Dispatch.h"

#define SIZE_BUFFER 10
#define TEXT_PORT 6716
#define FILE_PORT 6715

class Client {
	public:
		Client();
		void run(void);
		bool isRunning;
		virtual ~Client();

		/* Command
		 * Class holds information about various commands
		 * that can be called during runtime.
		 * To be populated at the start of client.cpp
		 ****************************************************/
		class Command
		{
			public:
				Command(std::string c, std::string d, std::string u) : cmd(c), dsc(d), use(u){};
				std::string cmd;
				std::string dsc;
				std::string use;
		};

	protected:

		/* Message
		 * Structure holds messages used in messages list
		 * (see below). Keeps track of speaker id and message
		 ****************************************************/
		typedef struct {
			int speaker;
			std::string message;
		} Message;

		/* Socket to server for sending text messages
		 ****************************************************/
		int textSock;

		/* Socket to server for sending files
		 ****************************************************/
		int fileSock;

		/* Max file descriptor for multiplexing
		 ****************************************************/
		int max_fd;

		/* Socket set for switching between STDIN and the server connection
		 ****************************************************/
		fd_set switcher;

		/* Host structure holds information about host
		 ****************************************************/
		struct hostent *host;

		/* Holds information about the connection
		 ****************************************************/
		struct sockaddr_in connection;

		/* Cursor position for the User Interface
		 ****************************************************/
		unsigned int cursor;

		/* Buffer scrollback position
		 ****************************************************/
		unsigned int scrollPos;

		/* Characters currently in the message buffer
		 ****************************************************/
		int characters;

		/* STDIN Message buffer
		 ****************************************************/
		char message[DATA_SIZE];

		/* Array of messages from clients/server
		 ****************************************************/
		std::vector<Message*> conversation;

		/* Username of the client.
		 ****************************************************/
		std::string username;

		// Operating Specifics
		virtual void catchInput(void) = 0;
		virtual void addLine(int, std::string) = 0;
		virtual void updateToolbar(void) = 0;
		virtual void updateWindow(void) = 0;
		virtual void drawConversation(void) = 0;

		// Standard Client Functions
		void clearTextField( void );

		/* Process any message in the format
		 * /command argument
		 * and run functions accordingly.
		 * For example, '/help' should call help()
		 ***************************************************/
		void processCommands( char* command );

		/* Dispatch a message to the server requesting the
		 * user list.
		 ***************************************************/
		void requestUserList( void );
		void processDispatch( Dispatch* d );
		void sendFile( std::string filename );
		bool connectTo( const std::string ip );
		void disconnect( void );
		bool validIP( const std::string ip );
		void loadCommands( void );
		void readLine( char*, FILE*);

		// Runtime Functions
		void nick( const char* newnick );
		void help( const char* command );
		void info( void );
		void quit( const char* message );
};

